package SnmpClients;



import java.io.IOException;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 * Classe responsável por fazer a ligação ao agente e fazer query's.
 * Mais especificamente, utiliza SNMP v2c. Importante para agentes que ainda não suportem a versão mais recente
 * 
 */
public class SnmpClientV2c {
    
    private Snmp snmp;
    private TransportMapping transport;
    private String address;
    
    
    /**
     * Construtor
     * 
     * @param ipAddressAndPort Endereço IP e porta do agente
     * @throws IOException
     */
    public SnmpClientV2c(String ipAddressAndPort) throws IOException{
        transport = new DefaultUdpTransportMapping();
        snmp = new Snmp(transport);
        address = ipAddressAndPort;

        start();
    }
    
    
    private void start() throws IOException {
        transport.listen();
    }
    
    /**
     * Vai buscar o valor de um objecto ao agente
     * 
     * @param oid OID do objecto do qual se prentede capturar o valor
     * @return O valor do objecto correspondente ao OID indicado
     * @throws IOException
     */
    public String getAsString(OID oid) throws IOException {
        ResponseEvent event = get(oid);
        return event.getResponse().get(0).getVariable().toString();
    }
    
    /**
     * Usado pelo método getAsString
     * 
     * @param oid
     * @return
     * @throws IOException
     */
    public ResponseEvent get(OID oid) throws IOException {
        PDU pdu = new PDU();
        pdu.add(new VariableBinding(oid));
        pdu.setType(PDU.GET);
        ResponseEvent event = this.snmp.send(pdu, getTarget());
        if(event != null) {
             return event;
        }
        throw new RuntimeException("GET timed out");
    }
    
        /**
     * Vai buscar o valor de varios objectos
     * 
     * @param oid OID's dos objectos do qual se pretende capturar o valor
     * @return PDU com os valores dos objectos
     * @throws IOException
     */
    public ResponseEvent getListAsString(OID[] oid) throws IOException{
        PDU pdu = new PDU();
        //pdu.add(new VariableBinding(oid));
        for(OID o : oid)
            pdu.add(new VariableBinding(o));
        //pdu.addAll(vbs);
        pdu.setType(PDU.GET);
        ResponseEvent event = snmp.send(pdu, getTarget());
        if(event != null) 
        {
             return event;//.get(0).getVariable().toString();
        }
        throw new RuntimeException("GET timed out");
    }
    
     /**
     * Define o agente ao qual o cliente snmpv2c se vai ligar
     * 
     * @return Target devolve um target correspondente ao endereço e porta guardado na variável address da instância.
     */
    private Target getTarget() {
        Address targetAddress = GenericAddress.parse(address);
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString("public"));
        target.setAddress(targetAddress);
        target.setRetries(2);
        target.setTimeout(1500);
        target.setVersion(SnmpConstants.version2c);
        return (Target) target;
    }
}